/*
 * usart.c
 *
 *  Created on: Jun 27, 2020
 *      Author: HYJ
 */

#include "usart.h"

DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
u8 aRxBuffer[1]; //HAL库使用的串口接收缓冲
struct UART_COMMON *uart1_common;

#ifdef UART_USE_DMA
/*
 *********************************************************************************************************
 * 函 数 名: DMA_Usart_Send
 * 功能说明: 串口发送功能函数
 * 形  参: buf，len
 * 返 回 值: 无
 *********************************************************************************************************
 */
void DMA_Usart_Send(uint8_t *buf, uint8_t len) //串口发送封装
{
	if (HAL_UART_Transmit_DMA(&uart1_common->uart_handle, buf, len) != HAL_OK) {
		Error_Handler();
	}
}

/*
 *********************************************************************************************************
 * 函 数 名: DMA_Usart1_Read
 * 功能说明: 串口接收功能函数
 * 形  参: Data,len
 * 返 回 值: 无
 *********************************************************************************************************
 */
void DMA_Usart1_Read(uint8_t *Data, uint8_t len) //串口接收封装
{
	HAL_UART_Receive_DMA(&uart1_common->uart_handle, Data, len); //重新打开DMA接收
}
#endif

void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle) {
	GPIO_COMMON *u1_txd = NULL, *u1_rxd = NULL;

	if (uartHandle->Instance == USART1) {
		/* USART1 clock enable */
		__HAL_RCC_USART1_CLK_ENABLE();

		//    /**USART1 GPIO Configuration
		//    PA9     ------> USART1_TX
		//    PA10     ------> USART1_RX
		//    */
		u1_txd = new_Gpio(u1_txd, GPIOA, GPIO_PIN_9, GPIO_MODE_AF_PP,
		GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);
		u1_rxd = new_Gpio(u1_rxd, GPIOA, GPIO_PIN_10, GPIO_MODE_INPUT,
		GPIO_NOPULL, GPIO_SPEED_FREQ_HIGH);
#ifdef UART_USE_DMA
		/* USART1 DMA Init */
		/* USART1_RX Init */
		__HAL_RCC_DMA1_CLK_ENABLE();
		/* DMA interrupt init */
		/* DMA1_Channel4_IRQn interrupt configuration */
		HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
		/* DMA1_Channel5_IRQn interrupt configuration */
		HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

		hdma_usart1_rx.Instance = DMA1_Channel5;
		hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
		hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
		hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
		hdma_usart1_rx.Init.Mode = DMA_NORMAL;
		hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
		if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) {
			Error_Handler();
		}

		__HAL_LINKDMA(uartHandle, hdmarx, hdma_usart1_rx);

		/* USART1_TX Init */
		hdma_usart1_tx.Instance = DMA1_Channel4;
		hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
		hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
		hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
		hdma_usart1_tx.Init.Mode = DMA_NORMAL;
		hdma_usart1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
		if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) {
			Error_Handler();
		}

		__HAL_LINKDMA(uartHandle, hdmatx, hdma_usart1_tx);

#endif
		HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(USART1_IRQn);
	}
}

void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle) {

	if (uartHandle->Instance == USART1) {
		__HAL_RCC_USART1_CLK_DISABLE();
		HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
#ifdef UART_USE_DMA
		/* USART1 DMA DeInit */
		HAL_DMA_DeInit(uartHandle->hdmarx);
		HAL_DMA_DeInit(uartHandle->hdmatx);
#endif
		HAL_NVIC_DisableIRQ(USART1_IRQn);
	}
}

void USART1_IRQHandler(void) {
#ifdef UART_USE_DMA
	uint32_t temp;

	if (__HAL_UART_GET_FLAG(&uart1_common->uart_handle,UART_FLAG_IDLE) != RESET)    //如果接受到了一帧数据
			{
		__HAL_UART_CLEAR_IDLEFLAG(&uart1_common->uart_handle);    //清除标志位
		HAL_UART_DMAStop(&uart1_common->uart_handle); //
		temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); // 获取DMA中未传输的数据个数
		uart1_common->rx_len = MAX_RX_LENGTH - temp; //总计数减去未传输的数据个数，得到已经接收的数据个数
		uart1_common->rx_flag = 1;	// 接受完成标志位置1
	}
	HAL_UART_IRQHandler(&uart1_common->uart_handle);
#else
	u32 timeout = 0;
	u32 maxDelay = 0x1FFFF;

	HAL_UART_IRQHandler(&huart1);	//调用HAL库中断处理公用函数

	timeout = 0;
	while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY)	//等待就绪
	{
		timeout++;	////超时处理
		if (timeout > maxDelay)
			break;
	}

	timeout = 0;
	while (HAL_UART_Receive_IT(&huart1, (u8*) aRxBuffer, 1) != HAL_OK)//一次处理完成之后，重新开启中断并设置RxXferCount为1
	{
		timeout++; //超时处理
		if (timeout > maxDelay)
			break;
	}
#endif
}

void uart_clear_rec(struct UART_COMMON *this) {
	memset(this->rx_buf, 0, this->rx_len);
	this->rx_flag = 0;
	this->rx_len = 0;
}

void uart_printf(struct UART_COMMON *this, char *fmt, ...) {	//通过任意串口发送字符串
	u16 i;
	va_list ap;
	va_start(ap, fmt);
	vsprintf((char*) this->tx_buf, fmt, ap);
	va_end(ap);
	i = strlen((const char*) this->tx_buf);		//此次发送数据的长度
#ifdef UART_USE_DMA
	HAL_UART_Transmit_DMA(&this->uart_handle, (uint8_t*) this->tx_buf, i);
#else
	HAL_UART_Transmit(&this->uart_handle, (uint8_t*) this->tx_buf, i, 0xffff);
#endif
}

UART_COMMON* new_Uart(struct UART_COMMON *this, USART_TypeDef *port, u32 baud)//串口的初始化与相关函数注册
{
	this = (struct UART_COMMON*) calloc(1, sizeof(struct UART_COMMON));
	this->uart_handle.Instance = port;
	this->uart_handle.Init.BaudRate = baud;
	this->uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
	this->uart_handle.Init.StopBits = UART_STOPBITS_1;
	this->uart_handle.Init.Parity = UART_PARITY_NONE;
	this->uart_handle.Init.Mode = UART_MODE_TX_RX;
	this->uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	this->uart_handle.Init.OverSampling = UART_OVERSAMPLING_16;
	if (HAL_UART_Init(&this->uart_handle) != HAL_OK) {
		Error_Handler();
	}

#ifdef UART_USE_DMA
	__HAL_UART_ENABLE_IT(&this->uart_handle, UART_IT_RXNE); //使能RXNE中断
	__HAL_UART_ENABLE_IT(&this->uart_handle, UART_IT_IDLE); //使能IDLE中断

	//DMA接收函数，此句一定要加，不加接收不到第一次传进来的实数据，是空的，且此时接收到的数据长度为缓存器的数据长度
	HAL_UART_Receive_DMA(&this->uart_handle, this->rx_buf,MAX_RX_LENGTH);
#else
	HAL_UART_Receive_IT(&this->uart_handle, (u8*) aRxBuffer, 1);
#endif
	this->UClearRec = uart_clear_rec;
	this->UPrintf = uart_printf;
	return this;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
#ifdef UART_USE_DMA
#else
	if (huart->Instance == USART1) //如果是串口1
	{
		if (((uart1_common->rx_flag) & 0x80) == 0) //接收未完成
				{
			if ((uart1_common->rx_flag) & 0x40) //接收到了0x0d
					{
				if (aRxBuffer[0] != 0x0a) {
					uart_clear_rec(uart1_common); //接收错误,重新开始
				} else
					uart1_common->rx_flag |= 0x80;	//接收完成了
			} else //还没收到0X0D
			{
				if (aRxBuffer[0] == 0x0d)
					uart1_common->rx_flag |= 0x40;
				else {
					uart1_common->rx_buf[uart1_common->rx_len++] = aRxBuffer[0];
					if (uart1_common->rx_len > (MAX_RX_LENGTH - 1)) {
						uart_clear_rec(uart1_common);	//接收错误,重新开始
					}
				}
			}
		}
	}
#endif
}
